﻿using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;
using Useful.GUI;

namespace Useful
{
    // TODO В сгенерированном дизайнером коде в ручную заменено: this.cbList = new ComboBox4();
    public partial class SearchedComboBox : UserControl
    {
        private bool enteredText = false;
        protected bool selectIndex = false;
        private int oldSelectedIndex = -1;
        private bool needTextChange = true;

        public bool ResizeDropDownToMaxString { get; set; }

        public event EventHandler<EventArgs> SelectedIndexChanged = delegate { };
        public event EventHandler<EventArgs> SelectedValueChanged = delegate { };

        public SearchedComboBox()
        {
            InitializeComponent();
        }

        public string Caption
        {
            get
            {
                return gbPanel.Text;
            }
            set
            {
                try
                {
                    gbPanel.Text = value;

                    Size sizeOld = TextRenderer.MeasureText("Header", gbPanel.Font);
                    Size size = TextRenderer.MeasureText(gbPanel.Text, gbPanel.Font);

                    tbSearch.Left += size.Width - sizeOld.Width;
                }
                catch (Exception ex)
                {
                    ProcessException(ex);
                }
            }
        }

        private void HideLable()
        {
            lSearch.Visible = false;
        }

        private void HideTextBox()
        {
            tbSearch.Visible = false;
            tbSearch.Text = String.Empty;
        }

        private void lSearch_MouseHover(object sender, EventArgs e)
        {
            try
            {
                oldSelectedIndex = cbList.SelectedIndex;

                HideLable();
                tbSearch.Visible = true;
                tbSearch.Focus();

                enteredText = false;
            }
            catch (Exception ex)
            {
                ProcessException(ex);
            }
        }

        private void tbSearch_MouseLeave(object sender, EventArgs e)
        {
            try
            {
                if (!enteredText)
                {
                    HideTextBox();
                    cbList.Focus();
                    lSearch.Visible = true;

                    cbList.DroppedDown = false;
                }
            }
            catch (Exception ex)
            {
                ProcessException(ex);
            }
        }

        private void tbSearch_KeyDown(object sender, KeyEventArgs e)
        {
            try
            {
                switch (e.KeyCode)
                {
                    case Keys.Enter:
                        HideTextBox();
                        cbList.Focus();
                        lSearch.Visible = true;

                        int oldIndex = cbList.SelectedIndex;

                        enteredText = false;
                        cbList.DroppedDown = false;

                        cbList.SelectedIndex = oldIndex;
                        break;
                    case Keys.Down:
                        if (cbList.SelectedIndex < cbList.Items.Count - 1)
                        {
                            selectIndex = true;
                            cbList.SelectedIndex++;
                            selectIndex = false;

                            needTextChange = false;
                            tbSearch.Text = cbList.GetItemText(cbList.SelectedItem);
                            tbSearch.SelectionStart = tbSearch.Text.Length - 1;
                            needTextChange = true;
                        }
                        break;
                    case Keys.Up:
                        if (cbList.SelectedIndex > 0)
                        {
                            selectIndex = true;
                            cbList.SelectedIndex--;
                            selectIndex = false;

                            needTextChange = false;
                            tbSearch.Text = cbList.GetItemText(cbList.SelectedItem);
                            tbSearch.SelectionStart = tbSearch.Text.Length - 1;
                            needTextChange = true;
                        }
                        break;
                    case Keys.Escape:
                        HideTextBox();
                        cbList.Focus();
                        lSearch.Visible = true;

                        enteredText = false;
                        cbList.DroppedDown = false;

                        cbList.SelectedIndex = oldSelectedIndex;
                        break;
                }
            }
            catch (Exception ex)
            {
                ProcessException(ex);
            }
        }

        private void tbSearch_TextChanged(object sender, EventArgs e)
        {
            try
            {
                if (needTextChange && !String.IsNullOrEmpty(tbSearch.Text))
                {
                    ProcessSearch(tbSearch.Text);

                    enteredText = true;
                    //cbList.DroppedDown = true;
                }
            }
            catch (Exception ex)
            {
                ProcessException(ex);
            }
        }

        protected virtual void ProcessSearch(string inText)
        {
            string text = inText.ToUpper();

            int i;
            for (i = 0; (i < cbList.Items.Count) && !cbList.GetItemText(cbList.Items[i]).ToUpper().Contains(text); i++) ;

            if (i < cbList.Items.Count)
            {
                selectIndex = true;
                cbList.SelectedIndex = i;
                selectIndex = false;
            }
        }

        protected ComboBox ComboBoxControl
        {
            get
            {
                return cbList;
            }
        }

        public object DataSource
        {
            get
            {
                return cbList.DataSource;
            }
			set
			{
				cbList.DataSource = value;
			}
        }

        private void cbList_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                if (!selectIndex)
                {
                    HideTextBox();
                    cbList.Focus();
                    lSearch.Visible = true;
                }

                Debug.WriteLine("cbList_SelectedIndexChanged");
                SelectedIndexChanged(this, EventArgs.Empty);
            }
            catch (Exception ex)
            {
                ProcessException(ex);
            }
        }

        private void tbSearch_Leave(object sender, EventArgs e)
        {
            try
            {
                HideTextBox();
                cbList.Focus();
                lSearch.Visible = true;

                int oldIndex = cbList.SelectedIndex;

                enteredText = false;
                cbList.DroppedDown = false;

                cbList.SelectedIndex = oldIndex;
            }
            catch (Exception ex)
            {
                ProcessException(ex);
            }
        }

        private static void ProcessException(Exception ex)
        {
            MessageBoxHelper.ShowError(ex);
        }

        private void cbList_DropDown(object sender, EventArgs e)
        {
            if (ResizeDropDownToMaxString)
                cbList.DropDownWidth = GuiHelper.GetComboBoxMaxTextWith(cbList);
        }

        public void Init(string display, string value, object dataSource)
        {
            GuiHelper.InitComboBox(ComboBoxControl, display, value, dataSource);
        }

        public void Init(string display, string value, BindingSource bs, object dataSource)
        {
            GuiHelper.InitComboBox(ComboBoxControl, display, value, bs, dataSource);
        }

        public void InitWidthDraw(string display, string value, object dataSource, DrawItemEventHandler drawItemEventHandler)
        {
            GuiHelper.InitComboBox(ComboBoxControl, display, value, dataSource);

            ComboBoxControl.DropDownHeight = 400;
            ComboBoxControl.DrawMode = DrawMode.OwnerDrawFixed;
            ComboBoxControl.DrawItem += drawItemEventHandler;
            ComboBoxControl.DropDownStyle = ComboBoxStyle.DropDownList;
        }

        public void InitWidthDraw(string display, string value, BindingSource bs, object dataSource, DrawItemEventHandler drawItemEventHandler)
        {
            GuiHelper.InitComboBox(ComboBoxControl, display, value, bs, dataSource);

            ComboBoxControl.DropDownHeight = 400;
            ComboBoxControl.DrawMode = DrawMode.OwnerDrawFixed;
            ComboBoxControl.DrawItem += drawItemEventHandler;
            ComboBoxControl.DropDownStyle = ComboBoxStyle.DropDownList;
        }

        public int? IntSelectedValue
        {
            get
            {
                return GuiHelper.GetComboBoxValue2(ComboBoxControl);
            }
			set
			{
				if (ComboBoxControl.Items.Count > 0)
					GuiHelper.SetComboBoxValue(ComboBoxControl, value);
			}
        }

		public int? IntSelectedValue2
		{
			get
			{
				return GuiHelper.GetComboBoxValue2(ComboBoxControl);
			}
			set
			{
				if (ComboBoxControl.Items.Count > 0)
					GuiHelper.SetComboBoxValue2(ComboBoxControl, value);
			}
		}

        public object SelectedValue
        {
            get
            {
                return ComboBoxControl.SelectedValue;
            }
            set
            {
                if (ComboBoxControl.Items.Count > 0)
                    ComboBoxControl.SelectedValue = value;
            }
        }

        public object SelectedItem
        {
            get
            {
                return ComboBoxControl.SelectedItem;
            }
        }

        public string StringSelectedValueOrDBNull
        {
            get
            {
                if (ComboBoxControl.SelectedValue != DBNull.Value && ComboBoxControl.SelectedValue != null)
                    return ComboBoxControl.SelectedValue.ToString();
                else
                    return null;
            }
            set
            {
                if (ComboBoxControl.Items.Count > 0)
                    ComboBoxControl.SelectedValue = (object)value ?? DBNull.Value;
            }
        }

        public int DropDownHeight
        {
            get
            {
                return ComboBoxControl.DropDownHeight;
            }

            set
            {
                ComboBoxControl.DropDownHeight = value;
            }
        }

        protected new bool DesignMode
        {
            get { return LicenseManager.UsageMode == LicenseUsageMode.Designtime || base.DesignMode; }
        }

        private void cbList_SelectedValueChanged(object sender, EventArgs e)
        {
            Debug.WriteLine("cbList_SelectedValueChanged");

            SelectedValueChanged(this, EventArgs.Empty);
        }
    }
}
